home *** CD-ROM | disk | FTP | other *** search
- /*==============================================================================
-
- FICHERO: PCX.C
-
- AUTOR: ANTONIO LADESA JURADO
-
- FECHA: 24/6/94
-
- DESCRIPCION:
-
- Fichero que contiene las estructuras, constantes, variables y funciones
- internas y externas para el procesamiento de ficheros PCX.
-
- ==============================================================================*/
-
-
- /*---- MODULOS USADOS --------------------------------------------------------*/
-
- #include <stdio.h>
- #include <alloc.h>
- #include <string.h>
-
- #include "global.h"
- #include "memoria.h"
- #include "video.h"
- #include "pcx.h"
- #include "error.h"
-
-
- /*---- ESTRUCTURAS, CONSTANTES Y VARIABLES LOCALES AL MODULO -----------------*/
-
-
- /* cabecera de un fichero pcx */
- typedef struct
- {
- char fabricante;
- char version;
- char codificacion;
- char bits_por_pixel;
- int xmin,ymin;
- int xmax,ymax;
- int ppp_hor;
- int ppp_ver;
- char paleta[48];
- char reservado;
- char planos_color;
- int bytes_por_linea;
- int tipo_paleta;
- char relleno[58];
- }
- CABpcx;
-
- /* cabecera del fichero PCX */
- static CABpcx cabecera;
- /* contadores auxiliares */
- static int iant=0,cant=0;
-
-
- /*---- DEFINICION DE LAS FUNCIONES INTERNAS ----------------------------------*/
-
-
- IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre);
- IMAGEN *PCXleerImagen(IMAGEN *c,FILE *);
- void PCXleerLinea(char *, FILE *,int);
-
- void PCXescribirImagen(IMAGEN *c,FILE *f);
- void PCXescribirLinea(char *p, FILE *f, int bytes);
- void PCXcrearCabecera(IMAGEN *c);
-
-
- /*---- CODIFICACION DE LAS FUNCIONES OFRECIDAS -------------------------------*/
-
-
- /*---- FUNCION: extern IMAGEN *PCXcargar(char *nombre,IMAGEN *c) ---------------
-
- Descripción:
-
- Esta función carga en memoria una imagen de tipo PCX.
-
- Parámetros:
-
- char *nombre : nombre del fichero a cargar
- IMAGEN *c : puntero a estructura que alberga la imagen
-
- Retorno:
-
- Puntero a la estructura de la imagen o NULL si hubo error
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern IMAGEN *PCXcargar(char *nombre,IMAGEN *c)
- {
- FILE *f;
-
- /* abrir el fichero */
- if((f = fopen(nombre, "rb")) != NULL)
- {
- /* leer cabecera PCX */
- if((c = PCXleerCabecera(c,f,nombre))!=NULL)
- /* leer imagen */
- c = PCXleerImagen(c,f);
- fclose(f);
- }
- else
- {
- ERRORponer(ERRapertura);
- return(NULL);
- }
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: extern int *PCXsalvar(char *nombre,IMAGEN *c) ------------------
-
- Descripción:
-
- Esta función salva en disco una imagen con formato PCX.
-
- Parámetros:
-
- char *nombre : nombre del fichero a salvar
- IMAGEN *c : puntero a estructura que alberga la imagen
-
- Retorno:
-
- - 0 si hay error
- - 1 en caso contrario
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern int PCXsalvar(char *fichero,IMAGEN *c)
- {
- /* puntero al fichero de salida */
- FILE *f;
-
- /* abrir el fichero */
- if((f = fopen(fichero, "wb")) == NULL)
- {
- ERRORponer(ERRapertura);
- return(0);
- }
- /* adecuar el modo de video a la imagen */
- if(c->modo == VIDEOvga && c->colores <= 16)
- c=VIDEOvision(c);
-
- /* crear la cabecera PCX */
- PCXcrearCabecera(c);
- /* escribir la cabecera PCX */
- if(fwrite((char *)&cabecera,1,sizeof(CABpcx),f) != sizeof(CABpcx))
- {
- ERRORponer(ERRescritura);
- fclose(f);
- return(0);
- }
- /* escribir la imagen PCX */
- PCXescribirImagen(c,f);
-
- /* si tiene más de 16 colores, escribir paleta PCX */
- if(c->modo == VIDEOvga)
- {
- fputc(0xC,f);
- fwrite(c->paleta,768,1,f);
- }
- fclose(f);
- return(1);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- CODIFICACION DE LAS FUNCIONES INTERNAS --------------------------------*/
-
-
- /*---- FUNCION: IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre) --------
-
- Descripción:
-
- Esta función reserva memoria para la imagen y lee la cabecera del fichero
- PCX.
-
- Parámetros:
-
-
- IMAGEN *c : puntero a estructura que alberga la imagen
- FILE *f : puntero al fichero
- char *nombre : nombre del fichero a cargar
-
- Retorno:
-
- Puntero a la estructura de la imagen o NULL si hubo error
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- IMAGEN *PCXleerCabecera(IMAGEN *c,FILE *f,char *nombre)
- {
- /* leer cabecera PCX */
- if(fread((char *)&cabecera,1,sizeof(CABpcx),f) == sizeof(CABpcx))
- {
- /* comprobar que es un PCX */
- if(cabecera.fabricante != 0x0a)
- {
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
- }
- else
- {
- ERRORponer(ERRlectura);
- return(NULL);
- }
-
- /* reservar memoria para la cabecera de trabajo */
- if((c=MEMreservarCAB(c))==NULL)
- {
- ERRORponer(ERRnoMemoria);
- return(NULL);
- }
-
- /* cargar cabecera de trabajo */
- strcpy(c->nombre,nombre);
- c->ancho = cabecera.xmax - cabecera.xmin + 1;
- c->alto = cabecera.ymax - cabecera.ymin + 1;
- c->bytes = cabecera.bytes_por_linea;
- c->formato = PCX;
-
- /* determinar tipo de imagen */
- switch(cabecera.bits_por_pixel)
- {
- case 1:
- {
- /* monocromática */
- if(cabecera.planos_color == 1)
- {
- c->modo = VIDEOmono;
- c->colores = 2;
- c->haypaleta = FALSO;
- }
- else
- /* 16 colores */
- if(cabecera.planos_color == 4)
- {
- c->modo = VIDEOega;
- c->colores = 16;
- c->bytes*=4;
- c->haypaleta = CIERTO;
- memcpy(c->paleta,&cabecera.paleta,48);
- }
- else
- {
- /* formato desconocido */
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
- };
- break;
-
- case 8:
- if(cabecera.planos_color != 1)
- {
- /* formato desconocido */
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
- /* 256 colores */
- c->modo = VIDEOvga;
- c->colores = 256;
- c->haypaleta = CIERTO;
- /* leer paleta 256 colores */
- fseek(f,-768L,SEEK_END);
- if(fread((char *)c->paleta,1,768,f) != 768)
- {
- ERRORponer(ERRlectura);
- return(NULL);
- }
- break;
-
- default:
- /* formato desconocido */
- ERRORponer(ERRnoTratado);
- return(NULL);
- }
-
- /* si no hay memoria para la imagen, liberar cabecera */
- if(!MEMreservar(c))
- {
- c =MEMliberar(c);
- ERRORponer(ERRnoMemoria);
- return(c);
- }
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: IMAGEN *PCXleerImagen(IMAGEN *c,FILE *f) -----------------------
-
- Descripción:
-
- Esta función carga en memoria una imagen de tipo PCX.
-
- Parámetros:
-
-
- IMAGEN *c : puntero a estructura que alberga la imagen
- FILE *f : puntero al fichero
-
- Retorno:
-
- Puntero a la estructura de la imagen
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- IMAGEN *PCXleerImagen(IMAGEN *c,FILE *f)
- {
- /* contador de líneas */
- int i;
- /* buffer */
- char p[ANCHO_MAXIMO];
-
- /* inicializar variables estáticas para la lectura de líneas */
- iant=cant=0;
- /* posicionar puntero al inicio de la imagen */
- fseek(f,128L,SEEK_SET);
- /* cargar imagen */
- for(i = 0; i < c->alto ; i++)
- {
- PCXleerLinea(p,f,c->bytes);
- MEMescribir(p,i,c);
- }
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void PCXleerLinea(char *p, FILE *f,int bytes) ------------------
-
- Descripción:
-
- Esta función lee una línea de un fichero PCX.
-
- Parámetros:
-
- char *p : puntero a buffer donde se almacena la línea
- FILE *f : puntero al fichero
- int bytes: numero de bytes por linea
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void PCXleerLinea(char *p, FILE *f,int bytes)
- {
- /* contadores */
- int n = 0,i,cont;
-
- memset(p,0,bytes);
- /* descomprimir línea */
- do
- {
- /* si hay bytes de esta línea leidos antes, llevarlos al buffer */
- if(iant)
- {
- i = iant;
- cont = cant;
- iant = cant = 0;
- while(i--)
- p[n++]=cont;
- }
- else
- {
- cont = fgetc(f) & 0xff;
- /* si hay un contador, guardarlo en 'i' */
- if( (cont & 0xC0) == 0xC0)
- {
- i = cont & 0x3F;
- /* leer dato */
- cont = fgetc(f) & 0xff;
- /* si sobrepasa el ancho, guardarlos para la siguiente línea */
- if(i+n > bytes)
- {
- cant = cont;
- iant = (i+n-bytes);
- i=bytes-n;
- }
- /* repetir el dato 'i' veces */
- while(i--)
- p[n++]=cont;
- }
- else
- /* si no hay contador, es un dato */
- p[n++]=cont;
- }
- }
- while(n < bytes);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void PCXcrearCabecera(IMAGEN *c) -------------------------------
-
- Descripción:
-
- Esta función crea una cabecera PCX.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void PCXcrearCabecera(IMAGEN *c)
- {
- /* rellenar los datos de la cabecera */
- cabecera.fabricante = 0x0A;
- cabecera.version = 5;
- cabecera.codificacion = 1;
- cabecera.xmin = cabecera.ymin = 0;
- cabecera.xmax = c->ancho - 1;
- cabecera.ymax = c->alto - 1;
- cabecera.ppp_hor = c->ancho;
- cabecera.ppp_ver = c->alto;
- cabecera.reservado=0;
- cabecera.tipo_paleta = 2;
- switch(c->modo)
- {
- case VIDEOmono:
- cabecera.bits_por_pixel = 1;
- cabecera.planos_color = 1;
- cabecera.bytes_por_linea = c->bytes;
- break;
- case VIDEOega:
- cabecera.bits_por_pixel = 1;
- cabecera.planos_color = 4;
- cabecera.bytes_por_linea = c->bytes/4;
- memcpy(cabecera.paleta,c->paleta,48);
- break;
- case VIDEOvga:
- cabecera.bits_por_pixel = 8;
- cabecera.planos_color = 1;
- cabecera.bytes_por_linea = c->bytes;
- break;
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void PCXescribirImagen(IMAGEN *c,FILE *f) ----------------------
-
- Descripción:
-
- Esta función graba la imagen en un fichero PCX.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
- FILE *f : puntero al fichero
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void PCXescribirImagen(IMAGEN *c,FILE *f)
- {
- /* contador de líneas */
- int i;
- /* buffer */
- char p[ANCHO_MAXIMO];
-
- /* salvar imagen */
- for(i = 0; i < c->alto;++i)
- {
- MEMleer(p,i,c);
- PCXescribirLinea(p,f,c->bytes);
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void PCXescribirLinea(char *p, FILE *f,int bytes) --------------
-
- Descripción:
-
- Esta función escribe una línea en un fichero PCX.
-
- Parámetros:
-
- char *p : puntero a buffer que alberga la línea
- FILE *f : puntero al fichero
- int bytes : numero de bytes por línea
-
- Retorno:
-
- Puntero a la estructura de la imagen o NULL si hubo error
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void PCXescribirLinea(char *p,FILE *f,int bytes)
- {
- /* contadores */
- unsigned int i=0,t=0;
-
- do
- {
- i=0;
- while((p[t+i]==p[t+i+1]) && ((t+i) < bytes) && (i<63))
- ++i;
- /* si es posible, grabar contador y dato */
- if(i>0)
- {
- fputc(i|0xC0,f);
- fputc(p[t],f);
- t+=i;
- }
- else
- {
- /* si el dato ex 0xC0, grabar un contador de 1, y el dato */
- if(((p[t]) & 0xC0) == 0xC0)
- fputc(0xC1,f);
- /* grabar dato */
- fputc(p[t++],f);
- }
- }while(t<bytes);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/